<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch} from 'vue'
import { useRouter, useRoute } from 'vue-router'
import * as kc from "klinecharts";

import {
  getStats,
  getKlineData,
  getFactorFieldList,
  getFieldData,
  getUdList,
} from "./api"

import {ElMessageBox} from 'element-plus';

const router = useRouter()
const route = useRoute()

type klchart = kc.Chart

type Stats = {
  facName: string,
  Sharp_Nv: number,
  CR_Nv: number,
  Sharp_Nv_Long: number,
  Sharp_Nv_Short: number,
  hdays: number,
  leve: number,
  reverseFlag: number,
  maxHoldDays: number
  maxddHoldDays: number
  version: number
};

type IndicatorInfo = {
  id: string,
  field: string[],
  isMainChart: boolean,
  type: string
}

const stats = ref<Stats[]>([])
const underlying = ref<string>("A")
const dialogIndicator = ref(false)
const defaultIndicatorForm = {
  id: '',
  field: [""],
  isMainChart: false,
  type: 'line'
}
const indicatorForm = ref<IndicatorInfo>(copy(defaultIndicatorForm))
const formLabelWidth = ref('60px')
const factorFileFieldList = ref<string[]>([])
const chart = ref<klchart | null>(null)
const indicatorMap = ref<Map<string, IndicatorInfo>>(new Map())
const mainPanList = ref<string[]>([])
const subPanList = ref<string[]>([])
const udOption = ref([]);
const mainPane = 'candle_pane'



function confirmMsg(id: string, confirmCb?:Function, cancelCb?:Function) {
  ElMessageBox.confirm(`是否删除 ${id}`, "删除确认", {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(
    () => {
      if (confirmCb)
        confirmCb(id)
    },
    () => {
      if (cancelCb)
        cancelCb(id)
    }
  )
}

function setMainIndicator(name: string) {
  if (chart.value) {
    chart.value.createIndicator(name, true, { id: mainPane })
  }
}

function setSubIndicator(name: string) {
  if (chart.value) {
    chart.value.createIndicator(name, false, { id: name })
  }
}

function removeAll()
{
  for (let value of indicatorMap.value.values()) {
    removeIndicator(value.id)
  }
}

function removeIndicator(id: string) {
  if (chart.value?.getIndicatorByPaneId(mainPane, id))
  {
    chart.value?.removeIndicator(mainPane, id)
  }
  if (chart.value?.getIndicatorByPaneId(id))
  {
    chart.value?.removeIndicator(id)
  }
  indicatorMap.value.delete(id)
}

function copy(obj: any) {
  return JSON.parse(JSON.stringify(obj))
}

async function addIndicator(isMainChart: boolean, id: string, field: string[], type: string) {
  removeIndicator(id)

  let indData = await getFieldData(route.params.workspace, route.params.facName, underlying.value, field)

  if (!indData)
    return

  kc.registerIndicator({
    name: id,
    calcParams: field,
    figures: field.map((p) => {
      return { key: p, title: p + ":", type: type }
    }),
    // 当计算参数改变时，希望提示的和参数一样，即title的值需要改变
    regenerateFigures: (params) => {
      return params.map((p, i) => {
        return { key: p, title: p + ":", type: type }
      })
    },
    // 计算结果
    calc: async (kLineDataList, { calcParams, figures }) => {
      let r = []
      for (let i = 0; i < kLineDataList.length; i++) {
        let item = {}
        calcParams.forEach(
          (p, j) => {
              item[p] = indData[p][i]
          });
        r.push(item)
      }
      return r
    }
  })

  if (isMainChart)
    setMainIndicator(id)
  else
    setSubIndicator(id)

  indicatorMap.value.set(id,{
    id: id,
    field: field,
    isMainChart: isMainChart,
    type: type
  })
}

function initChart()
{
  if (!chart.value)
    chart.value = kc.init('k-line-chart')
  chart.value?.clearData()
  // indicatorMap.value.clear()

  getKlineData(route.params.workspace, route.params.facName, underlying.value).then(data => {
    if (chart.value && data)
      chart.value.applyNewData(data)
  })

  for (let value of indicatorMap.value.values()) {
    addIndicator(value.isMainChart, value.id, value.field, value.type)
  }
}

watch(underlying, async (val, oldVal) => {
  initChart()
})

onMounted(async () => {
  // 展示stats文件
  getStats(route.params.workspace, route.params.facName).then(data => {
    if (data) {
      stats.value.length = 0;
      stats.value.push(
        {
          facName: route.params.facName as string,
          Sharp_Nv: data.Sharp_Nv,
          CR_Nv: data.CR_Nv,
          Sharp_Nv_Long: data.Sharp_Nv,
          Sharp_Nv_Short: data.Sharp_Nv_Short,
          hdays: data.hdays,
          leve: data.leve,
          reverseFlag: data.reverseFlag,
          maxHoldDays: data.maxHoldDays,
          maxddHoldDays: data.maxddHoldDays,
          version: data.version
        }
      )
    }
  })

  getFactorFieldList(route.params.workspace, route.params.facName).then((data: string[] | null) => {
    if (data) {
      factorFileFieldList.value = data
    }
  })

  getUdList(route.params.workspace, route.params.facName).then(data => {
      udOption.value = data;
    });

  initChart()
})

onUnmounted(() => {
  kc.dispose('chart')
})
</script>

<template>
  <div style="
  position:absolute;
  top:0;
  left:0;
  height: 800px;
  width: 1500px;">
    <el-container>
      <el-header style="height: 100px;">
        <el-table :data="stats" style="height: 100%; width: 100%;">
          <el-table-column prop="facName" label="名称" width="180">
          </el-table-column>
          <el-table-column property="Sharp_Nv" label="夏普" width="100" sortable>
          </el-table-column>
          <el-table-column property="CR_Nv" label="卡吗" width="100" sortable>
          </el-table-column>
          <el-table-column property="Sharp_Nv_Long" label="多头夏普" width="120" sortable>
          </el-table-column>
          <el-table-column property="Sharp_Nv_Short" label="空头夏普" width="120" sortable>
          </el-table-column>
          <el-table-column property="hdays" label="持仓周期" width="120" sortable>
          </el-table-column>
          <el-table-column property="leve" label="杠杆率" width="120" sortable>
          </el-table-column>
          <el-table-column property="reverseFlag" label="反转标志" width="120" sortable>
          </el-table-column>
          <el-table-column property="maxHoldDays" label="最大持仓天数" width="150" sortable>
          </el-table-column>
          <el-table-column property="maxddHoldDays" label="最大回撤天数" width="150" sortable>
          </el-table-column>
          <el-table-column property="version" label="版本" width="100" sortable>
          </el-table-column>
        </el-table>
      </el-header>
      <el-header style="height: 100px;">
        <el-row type="flex" justify="start" align="top">
          <el-col :span="20">
              <el-select v-model="underlying">
              <el-option
                v-for="item in udOption"
                :key="item"
                :label="item"
                :value="item"
              >
            </el-option>
          </el-select>
        </el-col>
          <el-col :span="20">
              <el-button type="primary" @click="dialogIndicator = true">添加指标</el-button>
          </el-col>
        </el-row>
      </el-header>
      <el-container>
        <el-aside>
          <el-card>
            <el-menu :default-openeds="['1', '2']">
              <el-submenu index="1">
                <el-menu-item-group title="双击删除" @dblclick="confirmMsg('全部指标', (id)=>removeAll())"></el-menu-item-group>
                <el-menu-item-group title="主图指标">
                  <el-menu-item  v-for="ind in Array.from(indicatorMap.values()).filter((i)=>i.isMainChart)" :key="ind.id" @dblclick="confirmMsg(ind.id, (id)=>removeIndicator(id))">{{ ind.id
                    }}</el-menu-item>
                </el-menu-item-group>
              </el-submenu>
              <el-submenu index="2">
                <el-menu-item-group title="子图指标">
                  <el-menu-item  v-for="ind in Array.from(indicatorMap.values()).filter((i)=>!i.isMainChart)" :key="ind.id" @dblclick="confirmMsg(ind.id, (id)=>removeIndicator(id))">{{ ind.id
                    }}</el-menu-item>
                </el-menu-item-group>
              </el-submenu>
            </el-menu>
          </el-card>
        </el-aside>
        <el-main style="height:700px; width: 100%;">
          <div id="k-line-chart" style="height:100%; width: 100%;"></div>
        </el-main>
      </el-container>
    </el-container>

    <el-dialog title="添加指标" v-model="dialogIndicator"
      @closed="indicatorForm = copy(defaultIndicatorForm);">
      <el-form :model="indicatorForm">
        <el-form-item label="id" :label-width="formLabelWidth">
          <el-input class="formInput" v-model="indicatorForm.id" autocomplete="true" placeholder="指标ID，要求唯一"></el-input>
        </el-form-item>
        <el-form-item label="field" :label-width="formLabelWidth">
          <div v-for="i in indicatorForm.field.length">
            <el-autocomplete class="inline-input formInput" v-model="indicatorForm.field[i - 1]" :fetch-suggestions="(queryString: string, cb: any) => {
              let result = queryString ? factorFileFieldList.filter(item => {
                return item.toLowerCase().includes(queryString.toLowerCase())
              }) : factorFileFieldList

              cb(result.map(v => ({
                value: v
              })))
            }" placeholder="数据字段"></el-autocomplete>
            <el-button link size="small" @click="indicatorForm.field.push('')">添加</el-button>
            <el-button link size="small"
              @click="indicatorForm.field.splice(i, 1);">删除</el-button>
          </div>
        </el-form-item>
        <el-form-item label="附加到主图">
          <el-switch v-model="indicatorForm.isMainChart"></el-switch>
        </el-form-item>
        <el-form-item label="类型">
          <el-select v-model="indicatorForm.type" placeholder="图形类型">
            <el-option label="line" value="line"></el-option>
            <el-option label="bar" value="bar"></el-option>
          </el-select>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogIndicator = false">取 消</el-button>
        <el-button type="primary"
          @click="dialogIndicator = false; addIndicator(indicatorForm.isMainChart, indicatorForm.id, indicatorForm.field, indicatorForm.type);">确
          定</el-button>
      </div>
    </el-dialog>
  </div>

</template>

<style>
.el-aside {

  color: #333;
  text-align: center;
  line-height: 400px;
}

.el-main {
  text-align: center;
  line-height: 160px;
}

.formInput.el-input,
.formInput.el-autocomplete {
  width: 300px;
}

body>.el-container {
  margin-bottom: 40px;
}

.el-container:nth-child(5) .el-aside,
.el-container:nth-child(6) .el-aside {
  line-height: 260px;
}

.el-container:nth-child(7) .el-aside {
  line-height: 320px;
}
</style>
